package draw;

import binarization.AdaptiveBinary;
import circles.DrawCircles;
import classifiers.AbstractDoAction;
import classifiers.CircleClassifier;
import classifiers.MouseClickListener;
import classifiers.SimpleDrawRegion;
import filters.AbstractColorFilter;
import filters.LogColorFilter;
import histogram.HistogramCreater;
import histogram.HistogramDescr;
import histogram.NeiroMarkImage;
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.filechooser.FileFilter;
import report.ReportGenerator;
import yaml.MitachElement;
import yaml.YamlReader;

public class ExploringMedics {

    public static void main(String[] args) {
        new ExploringMedics();
    }
    JFrame mainFrame = new JFrame("Exploring...");
    JButton path = new JButton("Path");
    JComboBox<String> typeBox = new JComboBox<String>();
    JButton recognize = new JButton("Recognize");
    JButton report = new JButton("Report");
//    String rootName = "med1.jpg";
    String rootName = "onlyMitach.jpg";
    //    String rootName = "6_20k.jpg";
//    String rootName = "Res_cutOrigin.bmp";
//    String rootName = "img002.jpg";
//    String rootName = "im3.jpg";
//    String rootName = "img007.jpg";
//    String rootName = "2_20k.jpg";
//    String rootName = "cutIm.png";
    BufferedImage rootImage;
    DrawPanel drawPanel;
    public static int width = 0;
    public static int height = 0;
    int[][] binaryImage;
    public static final int WHITE = 255;
    public static final int BLACK = 0;
    ArrayList<MitachElement> mitachList;
    public static MitachElement currentMitachProperties;
    private int[][] rootImageArray;

    public ExploringMedics() {
        init();
//        new MakeHistogram();
//        doBinary();
//        new ReadHistRes(rootImage);
//        drawPanel.repaint();
    }

    private void doBinary() {
        ArrayFromImage rootArrayImage = new ArrayFromImage(rootImage);

        int binArray[][] = rootArrayImage.getImageDescription();


        AbstractColorFilter logFilter = new LogColorFilter(binArray);
        logFilter.doFilted();
        binArray = logFilter.getImageDescription();

//        AbstractColorFilter powFilter = new PowerColorFilter(binArray);
//        powFilter.doFilted();
//        binArray = powFilter.getImageDescription();

//        AbstractColorFilter invertFilter = new InvertColorFilter(binArray);
//        invertFilter.doFilted();
//        binArray = invertFilter.getImageDescription();

//        AbstractColorFilter localFilter = new LocalColorFilter(binArray);
//        localFilter.doFilted();
//        binArray = localFilter.getImageDescription();

//        AbstractColorFilter invertFilter1 = new InvertColorFilter(binArray);
//        invertFilter1.doFilted();
//        binArray = invertFilter1.getImageDescription();

//        LaplasColorFilter laplasFilter = new LaplasColorFilter(binArray);
//        laplasFilter.setMask(LaplasColorFilter.TYPE_DIAG);
//        laplasFilter.doFilted();
//        binArray = laplasFilter.getImageDescription();

        AdaptiveBinary adaptBinary = new AdaptiveBinary();
        adaptBinary.setImage(binArray);
        binArray = adaptBinary.getBinaryImage();

//        SimpleBinary adaptBinary = new SimpleBinary();
//        adaptBinary.setImageDescr(binArray, 254);
//        binArray = adaptBinary.getImageDescr();

        BufferedImage binIm = ImageFromArray.createImageFromArray(binArray);
        AbstractDoAction simpleDrawRegion = new SimpleDrawRegion(binArray, rootImage);
        MouseClickListener regionDrawClass = new MouseClickListener(simpleDrawRegion, drawPanel);
        drawPanel.addMouseListener(regionDrawClass);
        drawPanel.setSrcImage(binIm);

//        AdaptiveBinary adaptBinary = new AdaptiveBinary();
//        adaptBinary.setImage(rootImage);
//        binaryImage = adaptBinary.getBinaryImage();
//
//        NoiseFilter noiseFilter = new NoiseFilter(binaryImage);
//        binaryImage = noiseFilter.getImageDescription();

        /*
        SizeFilter sizeFilter = new SizeFilter(binaryImage);
        binaryImage = sizeFilter.getImageDescription();
        
        BufferedImage binIm = ImageFromArray.createImageFromArray(binaryImage);
        
        drawPanel.setSrcImage(binIm);
        
        PerimetrClassifier perimAction = new PerimetrClassifier(binaryImage);
        //                          wMin  wMax hMin hMax sMin  sMax mindiv maxdiv
        perimAction.setExploy(10, 40, 10, 40, 50, 680, 20, 250);
        perimAction.exployAll();
        BufferedImage im = ImageFromArray.createImageFromArray(perimAction.getRegion());
        drawPanel.setSrcImage(im);
        
        MouseClikListener perimClass = new MouseClikListener(perimAction, drawPanel);
        drawPanel.setMouseAdapter(perimClass);
         */
//        AbstractDoAction circleAction = new CircleSquareAction(binaryImage);
//        MouseClikListener circleClass = new MouseClikListener(circleAction, drawPanel);
//        drawPanel.setMouseAdapter(circleClass);

//        AlphaTest alpha = new AlphaTest();
//        BufferedImage testAlpha = alpha.getImageTest();
//        drawPanel.setSrcImage(testAlpha);

    }
    NeiroMarkImage neiroMarker;
    CircleClassifier circleClassifier;

    private void init() {
        mainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        JPanel btnPan = new JPanel();
        path.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent ae) {
                report.setEnabled(false);
                JFileChooser chooser = new JFileChooser();
                try {
                    chooser.setSelectedFile(new File("D:\\java\\saves\\ExploringMedics\\srcImage\\lipid.bmp"));
                } catch (Exception e) {
                }
                chooser.setFileFilter(new FileFilter() {

                    @Override
                    public boolean accept(File file) {
                        if (file.isDirectory()) {
                            return true;
                        }
                        if (file.getName().toLowerCase().endsWith(".png")
                                || file.getName().toLowerCase().endsWith(".jpg")
                                || file.getName().toLowerCase().endsWith(".jpeg")
                                || file.getName().toLowerCase().endsWith(".bmp")) {
                            return true;
                        }
                        return false;
                    }

                    @Override
                    public String getDescription() {
                        return "jpg";
                    }
                });
                int retVal = chooser.showDialog(mainFrame, "Choose photo");
                if (retVal == JFileChooser.APPROVE_OPTION) {
                    File file = chooser.getSelectedFile();
                    if (file.isFile()) {
                        String name = file.getAbsolutePath();
                        readImage(name);
                        drawPanel.setSrcImage(rootImage);
                        width = rootImage.getWidth();
                        height = rootImage.getHeight();
                        drawPanel.setPreferredSize(new Dimension(width, height));
                        drawPanel.repaint();
                        mainFrame.pack();
                        mainFrame.setLocationRelativeTo(null);
                    }
                }
            }
        });

        YamlReader yamlReader = new YamlReader();
        try {
            mitachList = yamlReader.readConfig();
        } catch (FileNotFoundException ex) {
            Logger.getLogger(ExploringMedics.class.getName()).log(Level.SEVERE, null, ex);
        }

        typeBox.addItem("");

        for (MitachElement el : mitachList) {
            typeBox.addItem(el.getTypeName());
        }

        typeBox.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent ae) {
                report.setEnabled(false);
                JComboBox cb = (JComboBox) ae.getSource();
                if (cb.getSelectedIndex() > 0) {
                    currentMitachProperties = mitachList.get(cb.getSelectedIndex() - 1);
                    recognize.setEnabled(true);
                } else {
                    recognize.setEnabled(false);
                }
            }
        });


        report.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent ae) {
//TODO add this values
                long realsquare = 1000;
                long realscale = 1000;
                new ReportGenerator(neiroMarker.getResultMatrix(), circleClassifier.getMarkedImage(), realsquare, realscale);
            }
        });

        report.setEnabled(false);
        recognize.setEnabled(false);

        recognize.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent ae) {
                ArrayFromImage rootArrayImage = new ArrayFromImage(rootImage);
                int origin[][] = rootArrayImage.getImageDescription();
                HistogramCreater histCreater = new HistogramCreater(origin);

                HistogramDescr histDescr = histCreater.getHistogram();
                neiroMarker = new NeiroMarkImage(histDescr, rootImage);

                drawPanel.setSrcImage(neiroMarker.getPaintedImage());
                drawPanel.repaint();

                AbstractColorFilter logFilter = new LogColorFilter(origin);
                logFilter.doFilted();
                int[][] binArray = logFilter.getImageDescription();

                AdaptiveBinary adaptBinary = new AdaptiveBinary();
                adaptBinary.setImage(binArray);
                binArray = adaptBinary.getBinaryImage();

                circleClassifier = new CircleClassifier(neiroMarker.getResultMatrix(),
                        binArray);
                //                      wMin  wMax hMin hMax sMin  sMax mindiv maxdiv
                circleClassifier.setExploy(5, 60, 5, 60, 50, 650, 20, 200);
                circleClassifier.exployAll();
                int[][] markedImage = circleClassifier.getMarkedImage();

                BufferedImage binIm = ImageFromArray.createColorImageFromArray(origin, markedImage,
                        neiroMarker.getResultMatrix());

                drawPanel.setSrcImage(binIm);
                drawPanel.repaint();

                DrawFilter draw = new DrawFilter(origin, drawPanel.getSrcImage(), drawPanel,
                        markedImage, neiroMarker.getResultMatrix());

                drawPanel.addMouseMotionListener(draw);
                drawPanel.addMouseListener(draw);


//                AbstractDoAction neiroPaintCircles = new DrawCircles(neiroMarker.getResultMatrix(), 
//                        origin, binArray, markedImage, binIm);
//                MouseClickListener neiroCircles = new MouseClickListener(neiroPaintCircles, drawPanel);
//                drawPanel.addMouseListener(neiroCircles);
                report.setEnabled(true);
            }
        });

        btnPan.setLayout(new FlowLayout(FlowLayout.CENTER, 4, 4));
        btnPan.add(path);
        btnPan.add(typeBox);
        btnPan.add(recognize);
        btnPan.add(report);

        mainFrame.setLayout(new BorderLayout());
        mainFrame.add(btnPan, BorderLayout.NORTH);
        drawPanel = new DrawPanel();
        drawPanel.setPreferredSize(new Dimension(800, 600));
//        drawPanel.setBorder(BorderFactory.createTitledBorder(BorderFactory.createLineBorder(Color.black), "ылроыв"));
//        drawPanel.repaint();
        mainFrame.add(drawPanel, BorderLayout.CENTER);
        mainFrame.pack();
        mainFrame.setLocationRelativeTo(null);
        mainFrame.setVisible(true);
    }

    private void readImage(String imageName) {
        try {
            rootImage = ImageIO.read(new File(imageName));
            width = rootImage.getWidth();
            height = rootImage.getHeight();
        } catch (IOException ex) {
            System.out.println(ex.getMessage());
        }
    }

    public static void saveImage(BufferedImage srcImage) {
        try {
            int number = (int) (Math.random() * 100000);
            File f = new File("Res_bin_" + number + ".bmp");
            if (!f.exists()) {
                f.createNewFile();
            }
            ImageIO.write(srcImage, "bmp", f);

        } catch (IOException ex) {
            System.out.println(ex.getMessage());
        }
    }
}
